package com.uyun.config;

/**
 * Created by Administrator on 2016/8/11.
 */
import com.uyun.rbac.permission.dao.PermissionDao;
import com.uyun.rbac.permission.entity.PermissionEntity;
import com.uyun.rbac.shiro.MyRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import java.util.*;

/**
 * Shiro配置
 *
 **/

@Configuration
@Order(Ordered.LOWEST_PRECEDENCE-1)
public class ShiroConfig {

    private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
    /**
     * shiro过滤器，配置登录拦截等路由，并配置拦截规则
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(PermissionDao permissionDao) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的连接
        shiroFilterFactoryBean.setSuccessUrl("/main");
        // 若访问页面无权限则跳转的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/login");
        // 加载过滤规则
        List<Integer> permIds = permissionDao.getAllPermissionIds();
        List<PermissionEntity> list = new ArrayList<>();
        permIds.stream().forEach(permId->list.add(permissionDao.getPermissionEntityById(permId)));

        loadFilterChainDefinitions(shiroFilterFactoryBean,list);
        return shiroFilterFactoryBean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(getMyShiroRealm());
        //缓存
        defaultWebSecurityManager.setCacheManager(getEhCacheManager());
        return defaultWebSecurityManager;
    }


    @Bean(name="cacheManager")
    public CacheManager getEhCacheManager() {

        return new MemoryConstrainedCacheManager();
    }

    @Bean(name = "MyRealm")
    public MyRealm getMyShiroRealm() {
        MyRealm realm = new MyRealm();
        realm.setCacheManager(getEhCacheManager());
        return realm;
    }


    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     *shiroFilter权限控制规则
     */
    private void loadFilterChainDefinitions(ShiroFilterFactoryBean shiroFilterFactoryBean,List<PermissionEntity> allPermissionList){
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        // authc：这个代表必须验证后才能访问
        // anon：这个代表直接通过
        //这里写点固定不变的配置
        filterChainDefinitionMap.put("/login.htm", "anon");
        filterChainDefinitionMap.put("/logon", "anon");
        filterChainDefinitionMap.put("/signOut.htm", "anon");
        filterChainDefinitionMap.put("/captcha", "anon");
        //静态资源
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/dist/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/images/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/plugins/**", "anon");
        //filterChainDefinitionMap.put("/", "anon");  如果有主页 那就不拦截根目录
        //这边读取数据库
        for(PermissionEntity permissionEntity:allPermissionList){
            filterChainDefinitionMap.put(permissionEntity.getUrl(),"perms["+permissionEntity.getMapping()+"]");
        }

        //这个要放在最后，表示除了这个以外的都拦截不通过
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    }

}
